package com.example.ncov_management_system.service;

import cn.hutool.core.collection.ListUtil;
import com.example.ncov_management_system.dao.RecordDao;
import com.example.ncov_management_system.entity.Clbum;
import com.example.ncov_management_system.entity.Record;
import com.example.ncov_management_system.entity.Student;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@Slf4j
public class RecordService {
    @Autowired
    private RecordDao recordDao;

    public void add(Record record) {
        recordDao.save(record);
    }

    public boolean isReported(long student_id) {
        long count = recordDao.count(new Specification<Record>() {
            @Override
            public Predicate toPredicate(Root<Record> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<Student> student = root.get("student");
                Path<Long> id = student.get("id");
                Path<LocalDateTime> createTime = root.get("createTime");
                Predicate predicate = criteriaBuilder.equal(id, student_id);
                Predicate greaterThanOrEqualTo = criteriaBuilder.greaterThanOrEqualTo(createTime, LocalDateTime.of(LocalDate.now(), LocalTime.of(0, 0)));
                Predicate lessThan = criteriaBuilder.lessThan(createTime, LocalDateTime.of(LocalDate.now().plusDays(1), LocalTime.of(0, 0)));
                return criteriaBuilder.and(predicate, greaterThanOrEqualTo, lessThan);
            }
        });
        log.info("record count: {}", count);
        return count >= 1;
    }

    public Page<Record> findByClbumId(long clbumId, LocalDate localDate, int pn) {

        Page<Record> page = recordDao.findAll(new Specification<Record>() {
            @Override
            public Predicate toPredicate(Root<Record> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<Student> student = root.get("student");
                Path<Clbum> clbum = student.get("clbum");
                Path<Long> id = clbum.get("id");
                Predicate p_id = criteriaBuilder.equal(id, clbumId);
                Path<LocalDateTime> createTime = root.get("createTime");
                Predicate greaterThanOrEqualTo = criteriaBuilder.greaterThanOrEqualTo(createTime, LocalDateTime.of(localDate, LocalTime.of(0, 0)));
                Predicate lessThan = criteriaBuilder.lessThan(createTime, LocalDateTime.of(localDate.plusDays(1), LocalTime.of(0, 0)));
                return criteriaBuilder.and(p_id, greaterThanOrEqualTo, lessThan);

            }
        }, PageRequest.of(pn, 3));
        return page;
    }

    public List<Student> findReportedStudentByClbumId(long clbumId) {
        Set<Student> students = new HashSet<>();
        List<Record> records = recordDao.findAll(new Specification<Record>() {
            @Override
            public Predicate toPredicate(Root<Record> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<Student> student = root.get("student");
                Path<Clbum> clbum = student.get("clbum");
                Path<Long> id = clbum.get("id");
                Predicate p_id = criteriaBuilder.equal(id, clbumId);
                Path<LocalDateTime> createTime = root.get("createTime");
                Predicate greaterThanOrEqualTo = criteriaBuilder.greaterThanOrEqualTo(createTime, LocalDateTime.of(LocalDate.now(), LocalTime.of(0, 0)));
                Predicate lessThan = criteriaBuilder.lessThan(createTime, LocalDateTime.of(LocalDate.now().plusDays(1), LocalTime.of(0, 0)));
                return criteriaBuilder.and(p_id, greaterThanOrEqualTo, lessThan);
            }
        });
        for (Record record : records) {
            students.add(record.getStudent());
        }
        return ListUtil.toList(students);
    }
    public List<Student> findReportedStudent() {
        Set<Student> students = new HashSet<>();
        List<Record> records = recordDao.findAll(new Specification<Record>() {
            @Override
            public Predicate toPredicate(Root<Record> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<LocalDateTime> createTime = root.get("createTime");
                Predicate greaterThanOrEqualTo = criteriaBuilder.greaterThanOrEqualTo(createTime, LocalDateTime.of(LocalDate.now(), LocalTime.of(0, 0)));
                Predicate lessThan = criteriaBuilder.lessThan(createTime, LocalDateTime.of(LocalDate.now().plusDays(1), LocalTime.of(0, 0)));
                return criteriaBuilder.and(greaterThanOrEqualTo, lessThan);
            }
        });
        for (Record record : records) {
            students.add(record.getStudent());
        }
        return ListUtil.toList(students);
    }

}
